#include <sys/eventfd.h>
#include <unistd.h>
#include <iostream>
#include <thread>
#include <chrono>
#include <errno.h>
#include <cstring>

void demonstrate_initval() {
    std::cout << "\n=== 初始值演示 ===" << std::endl;
    
    // 初始值为0
    int efd1 = eventfd(0, EFD_NONBLOCK);
    
    // 初始值为5
    int efd2 = eventfd(5, EFD_NONBLOCK);
    
    uint64_t value;
    ssize_t result;
    
    // 尝试从初始值为0的eventfd读取
    result = read(efd1, &value, sizeof(value));
    if (result == -1) {
        std::cout << "efd1 (初始值0): 读取失败 - " << strerror(errno) << std::endl;
    }
    
    // 从初始值为5的eventfd读取
    result = read(efd2, &value, sizeof(value));
    if (result == sizeof(value)) {
        std::cout << "efd2 (初始值5): 读取成功，值 = " << value << std::endl;
    }
    
    // 再次尝试读取efd2
    result = read(efd2, &value, sizeof(value));
    if (result == -1) {
        std::cout << "efd2 再次读取: 失败 - " << strerror(errno) << std::endl;
    }
    
    close(efd1);
    close(efd2);
}

void demonstrate_blocking_vs_nonblocking() {
    std::cout << "\n=== 阻塞 vs 非阻塞演示 ===" << std::endl;
    
    // 阻塞模式
    int efd_blocking = eventfd(0, 0);
    
    // 非阻塞模式
    int efd_nonblocking = eventfd(0, EFD_NONBLOCK);
    
    uint64_t value;
    
    // 非阻塞读取（计数器为0）
    auto start = std::chrono::high_resolution_clock::now();
    ssize_t result = read(efd_nonblocking, &value, sizeof(value));
    auto end = std::chrono::high_resolution_clock::now();
    
    if (result == -1) {
        auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
        std::cout << "非阻塞读取: 立即返回错误 (" << duration.count() << "μs) - " 
                  << strerror(errno) << std::endl;
    }
    
    // 阻塞读取测试（在另一个线程中）
    std::cout << "开始阻塞读取测试..." << std::endl;
    
    std::thread reader([efd_blocking]() {
        uint64_t value;
        auto start = std::chrono::high_resolution_clock::now();
        
        ssize_t result = read(efd_blocking, &value, sizeof(value));
        
        auto end = std::chrono::high_resolution_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
        
        if (result == sizeof(value)) {
            std::cout << "阻塞读取: 成功读取值 " << value 
                      << " (等待了 " << duration.count() << "ms)" << std::endl;
        }
    });
    
    // 等待1秒后写入数据
    std::this_thread::sleep_for(std::chrono::seconds(1));
    
    uint64_t write_value = 42;
    write(efd_blocking, &write_value, sizeof(write_value));
    std::cout << "写入值 " << write_value << " 到阻塞eventfd" << std::endl;
    
    reader.join();
    
    close(efd_blocking);
    close(efd_nonblocking);
}

void demonstrate_semaphore_mode() {
    std::cout << "\n=== 普通模式 vs 信号量模式 ===" << std::endl;
    
    // 普通模式
    int efd_normal = eventfd(0, EFD_NONBLOCK);
    
    // 信号量模式
    int efd_semaphore = eventfd(0, EFD_NONBLOCK | EFD_SEMAPHORE);
    
    // 向两个eventfd写入相同的值
    uint64_t write_value = 5;
    write(efd_normal, &write_value, sizeof(write_value));
    write(efd_semaphore, &write_value, sizeof(write_value));
    
    std::cout << "向两个eventfd都写入值: " << write_value << std::endl;
    
    uint64_t value;
    
    // 普通模式读取
    if (read(efd_normal, &value, sizeof(value)) == sizeof(value)) {
        std::cout << "普通模式读取: " << value << " (一次读取全部)" << std::endl;
    }
    
    // 尝试再次读取普通模式
    if (read(efd_normal, &value, sizeof(value)) == -1) {
        std::cout << "普通模式再次读取: 失败 - " << strerror(errno) << std::endl;
    }
    
    // 信号量模式多次读取
    std::cout << "信号量模式连续读取: ";
    for (int i = 0; i < 6; i++) {
        if (read(efd_semaphore, &value, sizeof(value)) == sizeof(value)) {
            std::cout << value << " ";
        } else {
            std::cout << "失败(" << strerror(errno) << ") ";
            break;
        }
    }
    std::cout << std::endl;
    
    close(efd_normal);
    close(efd_semaphore);
}

void demonstrate_cloexec() {
    std::cout << "\n=== EFD_CLOEXEC 演示 ===" << std::endl;
    
    // 不带CLOEXEC
    int efd_normal = eventfd(0, EFD_NONBLOCK);
    
    // 带CLOEXEC
    int efd_cloexec = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
    
    std::cout << "创建两个eventfd:" << std::endl;
    std::cout << "  普通eventfd: " << efd_normal << std::endl;
    std::cout << "  CLOEXEC eventfd: " << efd_cloexec << std::endl;
    
    // 检查FD_CLOEXEC标志
    int flags_normal = fcntl(efd_normal, F_GETFD);
    int flags_cloexec = fcntl(efd_cloexec, F_GETFD);
    
    std::cout << "文件描述符标志:" << std::endl;
    std::cout << "  普通eventfd FD_CLOEXEC: " 
              << ((flags_normal & FD_CLOEXEC) ? "是" : "否") << std::endl;
    std::cout << "  CLOEXEC eventfd FD_CLOEXEC: " 
              << ((flags_cloexec & FD_CLOEXEC) ? "是" : "否") << std::endl;
    
    close(efd_normal);
    close(efd_cloexec);
}

void demonstrate_accumulation() {
    std::cout << "\n=== 事件累积演示 ===" << std::endl;
    
    int efd = eventfd(0, EFD_NONBLOCK);
    
    // 连续写入多个值
    for (uint64_t i = 1; i <= 3; i++) {
        write(efd, &i, sizeof(i));
        std::cout << "写入: " << i << std::endl;
    }
    
    // 一次读取累积值
    uint64_t total;
    if (read(efd, &total, sizeof(total)) == sizeof(total)) {
        std::cout << "累积读取: " << total << " (应该是 1+2+3=6)" << std::endl;
    }
    
    close(efd);
}

int main() {
    std::cout << "EventFD 参数和标志详解" << std::endl;
    std::cout << "=====================" << std::endl;
    
    demonstrate_initval();
    demonstrate_blocking_vs_nonblocking();
    demonstrate_semaphore_mode();
    demonstrate_cloexec();
    demonstrate_accumulation();
    
    return 0;
}
